#include "StdAfx.h"
#include "HardDriveSerialNumer.h"

int MasterHardDiskSerial::ReadPhysicalDriveInNTWithAdminRights (void)
{
   int iDone = FALSE;
   int iDrive = 0;

   for (iDrive = 0; iDrive < MAX_IDE_DRIVES; iDrive++)
   {
      HANDLE hPhysicalDriveIOCTL = 0;

         //  Try to get a handle to PhysicalDrive IOCTL, report failure
         //  and exit if can't.
      char cszDriveName [256];

      sprintf(cszDriveName, "\\\\.\\PhysicalDrive%d", iDrive);

         //  Windows NT, Windows 2000, must have admin rights
      hPhysicalDriveIOCTL = CreateFileA (cszDriveName,
                               GENERIC_READ | GENERIC_WRITE, 
                               FILE_SHARE_READ | FILE_SHARE_WRITE , NULL,
                               OPEN_EXISTING, 0, NULL);
      if (hPhysicalDriveIOCTL == INVALID_HANDLE_VALUE)
      {
		  SecureZeroMemory(m_cszErrorMessage,sizeof(m_cszErrorMessage));
		  sprintf(m_cszErrorMessage,"%d ReadPhysicalDriveInNTWithAdminRights ERROR ,CreateFileA(%s) returned INVALID_HANDLE_VALUE",__LINE__, cszDriveName);

      }
      else
      {
         GETVERSIONOUTPARAMS VersionParams;
         DWORD               dwBytesReturned = 0;

            // Get the version, etc of PhysicalDrive IOCTL
         memset ((void*) &VersionParams, 0, sizeof(VersionParams));

         if ( ! DeviceIoControl (hPhysicalDriveIOCTL, DFP_GET_VERSION,
                   NULL, 
                   0,
                   &VersionParams,
                   sizeof(VersionParams),
                   &dwBytesReturned, NULL) )
         {         

	           DWORD dwErr = GetLastError ();
			   SecureZeroMemory(m_cszErrorMessage,sizeof(m_cszErrorMessage));
	           sprintf(m_cszErrorMessage,"%d ReadPhysicalDriveInNTWithAdminRights ERROR DeviceIoControl() %d, DFP_GET_VERSION) returned 0, error is %d\n",__LINE__, (int) hPhysicalDriveIOCTL, (int) dwErr);
         }

            // If there is a IDE device at number "iI" issue commands
            // to the device
         if (VersionParams.bIDEDeviceMap <= 0)
         {
			 SecureZeroMemory(m_cszErrorMessage,sizeof(m_cszErrorMessage));
	         sprintf(m_cszErrorMessage,"%d ReadPhysicalDriveInNTWithAdminRights ERROR No device found at iPosition %d (%d)",__LINE__, (int) iDrive, (int) VersionParams.bIDEDeviceMap);
         }
         else
         {
            BYTE             bIDCmd = 0;   // IDE or ATAPI IDENTIFY cmd
            SENDCMDINPARAMS  scip;
            //SENDCMDOUTPARAMS OutCmd;

			   // Now, get the ID sector for all IDE devices in the system.
               // If the device is ATAPI use the IDE_ATAPI_IDENTIFY command,
               // otherwise use the IDE_ATA_IDENTIFY command
            bIDCmd = (VersionParams.bIDEDeviceMap >> iDrive & 0x10) ? \
                      IDE_ATAPI_IDENTIFY : IDE_ATA_IDENTIFY;

            memset (&scip, 0, sizeof(scip));
            memset (byIdOutCmd, 0, sizeof(byIdOutCmd));

            if ( DoIDENTIFY (hPhysicalDriveIOCTL, 
                       &scip, 
                       (PSENDCMDOUTPARAMS)&byIdOutCmd, 
                       (BYTE) bIDCmd,
                       (BYTE) iDrive,
                       &dwBytesReturned))
            {
               DWORD dwDiskData [256];
               int iIjk = 0;
               USHORT *punIdSector = (USHORT *)
                             ((PSENDCMDOUTPARAMS) byIdOutCmd) -> bBuffer;

               for (iIjk = 0; iIjk < 256; iIjk++)
                  dwDiskData [iIjk] = punIdSector [iIjk];

               PrintIdeInfo (iDrive, dwDiskData);

               iDone = TRUE;
            }
	    }

         CloseHandle (hPhysicalDriveIOCTL);
      }
   }

   return iDone;
}

int MasterHardDiskSerial::ReadPhysicalDriveInNTUsingSmart (void)
{
   int iDone = FALSE;
   int iDrive = 0;

   for (iDrive = 0; iDrive < MAX_IDE_DRIVES; iDrive++)
   {
      HANDLE hPhysicalDriveIOCTL = 0;

         //  Try to get a handle to PhysicalDrive IOCTL, report failure
         //  and exit if can't.
      char cszDriveName [256];

      sprintf(cszDriveName, "\\\\.\\PhysicalDrive%d", iDrive);

         //  Windows NT, Windows 2000, Windows Server 2003, Vista
      hPhysicalDriveIOCTL = CreateFileA (cszDriveName,
                               GENERIC_READ | GENERIC_WRITE, 
                               FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE, 
							   NULL, OPEN_EXISTING, 0, NULL);
      // if (hPhysicalDriveIOCTL == INVALID_HANDLE_VALUE)
      //    printf ("Unable to open physical iDrive %d, error code: 0x%lX\n",
      //            iDrive, GetLastError ());

      if (hPhysicalDriveIOCTL == INVALID_HANDLE_VALUE)
      {
			 SecureZeroMemory(m_cszErrorMessage,sizeof(m_cszErrorMessage));
			 sprintf(m_cszErrorMessage,"%d ReadPhysicalDriveInNTUsingSmart ERROR, CreateFileA(%s) returned INVALID_HANDLE_VALUE Error Code %d",__LINE__, cszDriveName, GetLastError ());
      }
      else
      {
         GETVERSIONINPARAMS GetVersionParams;
         DWORD dwBytesReturned = 0;

            // Get the version, etc of PhysicalDrive IOCTL
         memset ((void*) & GetVersionParams, 0, sizeof(GetVersionParams));

         if ( ! DeviceIoControl (hPhysicalDriveIOCTL, SMART_GET_VERSION,
                   NULL, 
                   0,
     			   &GetVersionParams, sizeof (GETVERSIONINPARAMS),
				   &dwBytesReturned, NULL) )
         {         
	           DWORD dwErr = GetLastError ();
			   SecureZeroMemory(m_cszErrorMessage,sizeof(m_cszErrorMessage));
	           sprintf(m_cszErrorMessage,"\n%d ReadPhysicalDriveInNTUsingSmart ERROR DeviceIoControl(%d, SMART_GET_VERSION) returned 0, error is %d",__LINE__, (int) hPhysicalDriveIOCTL, (int) dwErr);
         }
         else
         {
			 	// Print the SMART version
           	// PrintVersion (& GetVersionParams);
	           // Allocate the command cszBuffer
			ULONG CommandSize = sizeof(SENDCMDINPARAMS) + IDENTIFY_BUFFER_SIZE;
        	PSENDCMDINPARAMS Command = (PSENDCMDINPARAMS) malloc (CommandSize);
	           // Retrieve the IDENTIFY data
	           // Prepare the command
#define ID_CMD          0xEC            // Returns ID sector for ATA
			Command -> irDriveRegs.bCommandReg = ID_CMD;
			DWORD BytesReturned = 0;
	        if ( ! DeviceIoControl (hPhysicalDriveIOCTL, 
				                    SMART_RCV_DRIVE_DATA, Command, sizeof(SENDCMDINPARAMS),
									Command, CommandSize,
									&BytesReturned, NULL) )
            {
			   SecureZeroMemory(m_cszErrorMessage,sizeof(m_cszErrorMessage));
	           sprintf(m_cszErrorMessage,"SMART_RCV_DRIVE_DATA IOCTL");
		      
				// Print the error
		        //PrintError ("SMART_RCV_DRIVE_DATA IOCTL", GetLastError());
	        } 
			else
			{
        	       // Print the IDENTIFY data
                DWORD dwDiskData [256];
                USHORT *punIdSector = (USHORT *)
                             (PIDENTIFY_DATA) ((PSENDCMDOUTPARAMS) Command) -> bBuffer;

                for (int iIjk = 0; iIjk < 256; iIjk++)
                   dwDiskData [iIjk] = punIdSector [iIjk];

                PrintIdeInfo (iDrive, dwDiskData);
                iDone = TRUE;
			}
	           // Done
            CloseHandle (hPhysicalDriveIOCTL);
			free (Command);
		 }
      }
   }

   return iDone;
}
																		
char * MasterHardDiskSerial::flipAndCodeBytes ( int iPos, int iFlip, const char * pcszStr, char * pcszBuf)
{
   int iI;
   int iJ = 0;
   int iK = 0;

   pcszBuf [0] = '\0';
   if (iPos <= 0)
      return pcszBuf;

   if ( ! iJ)
   {
      char cP = 0;
      // First try to gather all characters representing hex digits only.
      iJ = 1;
      iK = 0;
      pcszBuf[iK] = 0;
      for (iI = iPos; iJ && !(pcszStr[iI] == '\0'); ++iI)
      {
		char cC = tolower(pcszStr[iI]);
		if (isspace(cC))
			cC = '0';
		++cP;
		pcszBuf[iK] <<= 4;

		if (cC >= '0' && cC <= '9')
			pcszBuf[iK] |= (char) (cC - '0');
		else if (cC >= 'a' && cC <= 'f')
			pcszBuf[iK] |= (char) (cC - 'a' + 10);
		else
		{
			iJ = 0;
			break;
		}

		if (cP == 2)
		{
			if ((pcszBuf[iK] != '\0') && ! isprint(pcszBuf[iK]))
			{
				iJ = 0;
				break;
			}
			++iK;
			cP = 0;
			pcszBuf[iK] = 0;
		}

      }
   }

   if ( ! iJ)
   {
      // There are non-digit characters, gather them as is.
      iJ = 1;
      iK = 0;
      for (iI = iPos; iJ && (pcszStr[iI] != '\0'); ++iI)
      {
	     char cC = pcszStr[iI];

	     if ( ! isprint(cC))
	     {
	        iJ = 0;
	        break;
	     }

	     pcszBuf[iK++] = cC;
      }
   }

   if ( ! iJ)
   {
      // The characters are not there or are not printable.
      iK = 0;
   }

   pcszBuf[iK] = '\0';

   if (iFlip)
      // Flip adjacent characters
      for (iJ = 0; iJ < iK; iJ += 2)
      {
	     char t = pcszBuf[iJ];
	     pcszBuf[iJ] = pcszBuf[iJ + 1];
	     pcszBuf[iJ + 1] = t;
      }

   // Trim any beginning and end space
   iI = iJ = -1;
   for (iK = 0; (pcszBuf[iK] != '\0'); ++iK)
   {
      if (! isspace(pcszBuf[iK]))
      {
	     if (iI < 0)
	        iI = iK;
	     iJ = iK;
      }
   }

   if ((iI >= 0) && (iJ >= 0))
   {
      for (iK = iI; (iK <= iJ) && (pcszBuf[iK] != '\0'); ++iK)
         pcszBuf[iK - iI] = pcszBuf[iK];
      pcszBuf[iK - iI] = '\0';
   }

   return pcszBuf;
}

int MasterHardDiskSerial::ReadPhysicalDriveInNTWithZeroRights (void)
{
   int iDone = FALSE;
   int iDrive = 0;

   for (iDrive = 0; iDrive < MAX_IDE_DRIVES; iDrive++)
   {
      HANDLE hPhysicalDriveIOCTL = 0;

         //  Try to get a handle to PhysicalDrive IOCTL, report failure
         //  and exit if can't.
      char cszDriveName [256];

      sprintf(cszDriveName,"\\\\.\\PhysicalDrive%d", iDrive);

         //  Windows NT, Windows 2000, Windows XP - admin rights not required
      hPhysicalDriveIOCTL = CreateFileA (cszDriveName, 0,
                               FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
                               OPEN_EXISTING, 0, NULL);
      if (hPhysicalDriveIOCTL == INVALID_HANDLE_VALUE)
      {
			SecureZeroMemory(m_cszErrorMessage,sizeof(m_cszErrorMessage));
			sprintf(m_cszErrorMessage,"%d ReadPhysicalDriveInNTWithZeroRights ERROR CreateFileA(%s) returned INVALID_HANDLE_VALUE",__LINE__, cszDriveName);
      }
      else
      {
		 STORAGE_PROPERTY_QUERY query;
         DWORD dwBytesReturned = 0;
		 char cszBuffer [10000];

         memset ((void *) &query, 0, sizeof (query));
		 query.PropertyId = StorageDeviceProperty;
		 query.QueryType = PropertyStandardQuery;

		 memset (cszBuffer, 0, sizeof (cszBuffer));

         if ( DeviceIoControl (hPhysicalDriveIOCTL, IOCTL_STORAGE_QUERY_PROPERTY,
                   &query,
                   sizeof (query),
				   & cszBuffer,
				   sizeof (cszBuffer),
                   & dwBytesReturned, NULL) )
         {         
			 STORAGE_DEVICE_DESCRIPTOR * descrip = (STORAGE_DEVICE_DESCRIPTOR *) & cszBuffer;
			 char cszSerialNumber [1000];
			 char cszModelNumber [1000];
             char cszVendorId [1000];
	         char cszProductRevision [1000];

             flipAndCodeBytes ( descrip -> VendorIdOffset,
			                    0,cszBuffer, cszVendorId );
	         flipAndCodeBytes ( descrip -> ProductIdOffset,
			                    0,cszBuffer, cszModelNumber );
	         flipAndCodeBytes ( descrip -> ProductRevisionOffset,
			                    0,cszBuffer, cszProductRevision );
	         flipAndCodeBytes ( descrip -> SerialNumberOffset,
			                    1,cszBuffer, cszSerialNumber );

			 if (0 == m_cszHardDriveSerialNumber [0] &&
						//  serial number must be alphanumeric
			            //  (but there can be leading spaces on IBM drives)
				   (iswalnum (cszSerialNumber [0]) || iswalnum (cszSerialNumber [19])))
			 {
				strcpy(m_cszHardDriveSerialNumber,	cszSerialNumber);
				strcpy(m_cszHardDriveModelNumber,	 cszModelNumber);
				iDone = TRUE;
			 }
	           // Get the disk iDrive geometry.
	         memset (cszBuffer, 0, sizeof(cszBuffer));
	         if ( ! DeviceIoControl (hPhysicalDriveIOCTL,
			          IOCTL_DISK_GET_DRIVE_GEOMETRY_EX,
			          NULL,
			          0,
			          &cszBuffer,
			          sizeof(cszBuffer),
			          &dwBytesReturned,
			          NULL))
	         {
				SecureZeroMemory(m_cszErrorMessage,sizeof(m_cszErrorMessage));
				sprintf(m_cszErrorMessage,"%s ReadPhysicalDriveInNTWithZeroRights ERROR DeviceIoControl(), IOCTL_DISK_GET_DRIVE_GEOMETRY_EX) returned 0", cszDriveName);
			}
	         else
	         {         
	            DISK_GEOMETRY_EX* geom = (DISK_GEOMETRY_EX*) &cszBuffer;
	            int iFixed = (geom->Geometry.MediaType == FixedMedia);
	            __int64 i64Size = geom->DiskSize.QuadPart;
				     
	        }
         }
		 else
		 {
			 DWORD dwErr = GetLastError ();
			 SecureZeroMemory(m_cszErrorMessage,sizeof(m_cszErrorMessage));
			 sprintf(m_cszErrorMessage,"DeviceIOControl IOCTL_STORAGE_QUERY_PROPERTY error = %d\n", dwErr);

		 }

         CloseHandle (hPhysicalDriveIOCTL);
      }
   }

   return iDone;
}

BOOL MasterHardDiskSerial::DoIDENTIFY (HANDLE hPhysicalDriveIOCTL, PSENDCMDINPARAMS pSCIP,
                 PSENDCMDOUTPARAMS pSCOP, BYTE bIDCmd, BYTE bDriveNum,
                 PDWORD lpcbBytesReturned)
{
      // Set up data structures for IDENTIFY command.
   pSCIP -> cBufferSize = IDENTIFY_BUFFER_SIZE;
   pSCIP -> irDriveRegs.bFeaturesReg = 0;
   pSCIP -> irDriveRegs.bSectorCountReg = 1;
   //pSCIP -> irDriveRegs.bSectorNumberReg = 1;
   pSCIP -> irDriveRegs.bCylLowReg = 0;
   pSCIP -> irDriveRegs.bCylHighReg = 0;

      // Compute the iDrive number.
   pSCIP -> irDriveRegs.bDriveHeadReg = 0xA0 | ((bDriveNum & 1) << 4);

      // The command can either be IDE identify or ATAPI identify.
   pSCIP -> irDriveRegs.bCommandReg = bIDCmd;
   pSCIP -> bDriveNumber = bDriveNum;
   pSCIP -> cBufferSize = IDENTIFY_BUFFER_SIZE;

   return ( DeviceIoControl (hPhysicalDriveIOCTL, DFP_RECEIVE_DRIVE_DATA,
               (LPVOID) pSCIP,
               sizeof(SENDCMDINPARAMS) - 1,
               (LPVOID) pSCOP,
               sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1,
               lpcbBytesReturned, NULL) );
}

int MasterHardDiskSerial::ReadIdeDriveAsScsiDriveInNT (void)
{
   int iDone = FALSE;
   int iController = 0;

   for (iController = 0; iController < 2; iController++)
   {
      HANDLE hScsiDriveIOCTL = 0;
      char   cszDriveName [256];

         //  Try to get a handle to PhysicalDrive IOCTL, report failure
         //  and exit if can't.
      sprintf(cszDriveName, "\\\\.\\Scsi%d:", iController);

         //  Windows NT, Windows 2000, any rights should do
      hScsiDriveIOCTL = CreateFileA (cszDriveName,
                               GENERIC_READ | GENERIC_WRITE, 
                               FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
                               OPEN_EXISTING, 0, NULL);
     

      if (hScsiDriveIOCTL != INVALID_HANDLE_VALUE)
      {
         int iDrive = 0;

         for (iDrive = 0; iDrive < 2; iDrive++)
         {
            char cszBuffer [sizeof (SRB_IO_CONTROL) + SENDIDLENGTH];
            SRB_IO_CONTROL *cP = (SRB_IO_CONTROL *) cszBuffer;
            SENDCMDINPARAMS *pin =
                   (SENDCMDINPARAMS *) (cszBuffer + sizeof (SRB_IO_CONTROL));
            DWORD dwDummy;
   
            memset (cszBuffer, 0, sizeof (cszBuffer));
            cP -> HeaderLength = sizeof (SRB_IO_CONTROL);
            cP -> Timeout = 10000;
            cP -> Length = SENDIDLENGTH;
            cP -> ControlCode = IOCTL_SCSI_MINIPORT_IDENTIFY;
            strncpy ((char *) cP -> Signature, "SCSIDISK", 8);
  
            pin -> irDriveRegs.bCommandReg = IDE_ATA_IDENTIFY;
            pin -> bDriveNumber = iDrive;

            if (DeviceIoControl (hScsiDriveIOCTL, IOCTL_SCSI_MINIPORT, 
                                 cszBuffer,
                                 sizeof (SRB_IO_CONTROL) +
                                         sizeof (SENDCMDINPARAMS) - 1,
                                 cszBuffer,
                                 sizeof (SRB_IO_CONTROL) + SENDIDLENGTH,
                                 &dwDummy, NULL))
            {
               SENDCMDOUTPARAMS *pOut =
                    (SENDCMDOUTPARAMS *) (cszBuffer + sizeof (SRB_IO_CONTROL));
               IDSECTOR *pId = (IDSECTOR *) (pOut -> bBuffer);
               if (pId -> sModelNumber [0])
               {
                  DWORD dwDiskData [256];
                  int iIjk = 0;
                  USHORT *punIdSector = (USHORT *) pId;
          
                  for (iIjk = 0; iIjk < 256; iIjk++)
                     dwDiskData [iIjk] = punIdSector [iIjk];

                  PrintIdeInfo (iController * 2 + iDrive, dwDiskData);

                  iDone = TRUE;
               }
            }
         }
         CloseHandle (hScsiDriveIOCTL);
      }
   }

   return iDone;
}

void MasterHardDiskSerial::PrintIdeInfo (int iDrive, DWORD dwDiskData [256])
{
   char cszSerialNumber [1024];
   char cszModelNumber [1024];
   char cszRevisionNumber [1024];
   char bufferSize [32];

   __int64 i64Sectors = 0;
   __int64 i64Byte = 0;

      //  copy the hard iDrive serial number to the cszBuffer
   ConvertToString (dwDiskData, 10, 19, cszSerialNumber);
   ConvertToString (dwDiskData, 27, 46, cszModelNumber);
   ConvertToString (dwDiskData, 23, 26, cszRevisionNumber);
   sprintf(bufferSize, "%u", dwDiskData [21] * 512);

   if (0 == m_cszHardDriveSerialNumber [0] &&
       //  serial number must be alphanumeric
       //  (but there can be leading spaces on IBM drives)
       (isalnum (cszSerialNumber [0]) || isalnum (cszSerialNumber [19])))
   {
      strcpy(m_cszHardDriveSerialNumber, cszSerialNumber);
      strcpy(m_cszHardDriveModelNumber, cszModelNumber);
   }

}

long MasterHardDiskSerial::getHardDriveComputerID ()
{
   int iDone = FALSE;
   // char string [1024];
   __int64 i64Id = 0;
   OSVERSIONINFO version;

   strcpy(m_cszHardDriveSerialNumber, "");

   memset (&version, 0, sizeof (version));
   version.dwOSVersionInfoSize = sizeof (OSVERSIONINFO);
   GetVersionEx (&version);
   if (version.dwPlatformId == VER_PLATFORM_WIN32_NT)
	{
		  //  this works under WinNT4 or Win2K if you have admin rights
		iDone = ReadPhysicalDriveInNTWithAdminRights ();

			//  this should work in WinNT or Win2K if previous did not work
			//  this is kind of a backdoor via the SCSI mini port driver into
			//     the IDE drives
		if ( ! iDone) 
			iDone = ReadIdeDriveAsScsiDriveInNT ();

		  //  this works under WinNT4 or Win2K or WinXP if you have any rights
		if ( ! iDone)
			iDone = ReadPhysicalDriveInNTWithZeroRights ();

		  //  this works under WinNT4 or Win2K or WinXP or Windows Server 2003 or Vista if you have any rights
		if ( ! iDone)
			iDone = ReadPhysicalDriveInNTUsingSmart ();
   }
   
   if (m_cszHardDriveSerialNumber [0] > 0)
   {
      char *cP = m_cszHardDriveSerialNumber;

         //  ignore first 5 characters from western digital hard drives if
         //  the first four characters are WD-W
      if ( ! strncmp (m_cszHardDriveSerialNumber, "WD-W", 4)) 
         cP += 5;
      for ( ; cP && *cP; cP++)
      {
         if ('-' == *cP) 
            continue;
         i64Id *= 10;
         switch (*cP)
         {
            case '0': i64Id += 0; break;
            case '1': i64Id += 1; break;
            case '2': i64Id += 2; break;
            case '3': i64Id += 3; break;
            case '4': i64Id += 4; break;
            case '5': i64Id += 5; break;
            case '6': i64Id += 6; break;
            case '7': i64Id += 7; break;
            case '8': i64Id += 8; break;
            case '9': i64Id += 9; break;
            case 'a': case 'A': i64Id += 10; break;
            case 'b': case 'B': i64Id += 11; break;
            case 'c': case 'C': i64Id += 12; break;
            case 'd': case 'D': i64Id += 13; break;
            case 'e': case 'E': i64Id += 14; break;
            case 'f': case 'F': i64Id += 15; break;
            case 'g': case 'G': i64Id += 16; break;
            case 'h': case 'H': i64Id += 17; break;
            case 'i': case 'I': i64Id += 18; break;
            case 'j': case 'J': i64Id += 19; break;
            case 'k': case 'K': i64Id += 20; break;
            case 'l': case 'L': i64Id += 21; break;
            case 'm': case 'M': i64Id += 22; break;
            case 'n': case 'N': i64Id += 23; break;
            case 'o': case 'O': i64Id += 24; break;
            case 'p': case 'P': i64Id += 25; break;
            case 'q': case 'Q': i64Id += 26; break;
            case 'r': case 'R': i64Id += 27; break;
            case 's': case 'S': i64Id += 28; break;
            case 't': case 'T': i64Id += 29; break;
            case 'u': case 'U': i64Id += 30; break;
            case 'v': case 'V': i64Id += 31; break;
            case 'w': case 'W': i64Id += 32; break;
            case 'x': case 'X': i64Id += 33; break;
            case 'y': case 'Y': i64Id += 34; break;
            case 'z': case 'Z': i64Id += 35; break;
         }                            
      }
   }

   i64Id %= 100000000;
   if (strstr (m_cszHardDriveModelNumber, "IBM-"))
      i64Id += 300000000;
   else if (strstr (m_cszHardDriveModelNumber, "MAXTOR") ||
            strstr (m_cszHardDriveModelNumber, "Maxtor"))
      i64Id += 400000000;
   else if (strstr (m_cszHardDriveModelNumber, "WDC "))
      i64Id += 500000000;
   else
      i64Id += 600000000;

   return (long) i64Id;
}

int MasterHardDiskSerial::GetSerialNo(TCHAR* lpSerialNumber, int nWcharSize)
{
    getHardDriveComputerID();
	size_t numberLength = strlen(m_cszHardDriveSerialNumber);
    if (numberLength == 0)
        return -1;

#ifdef _UNICODE
	::MultiByteToWideChar(CP_UTF8, NULL, m_cszHardDriveSerialNumber, -1, lpSerialNumber, nWcharSize);
#else
	_tcscpy(lpSerialNumber, m_cszHardDriveSerialNumber);
#endif

	return numberLength;
}

char *MasterHardDiskSerial::ConvertToString (DWORD dwDiskData [256],
		       int iFirstIndex,
		       int iLastIndex,
		       char* pcszBuf)
{
   int iIndex = 0;
   int iPosition = 0;

   //  each integer has two characters stored in it backwards

   // Removes the spaces from the serial no
   for ( iIndex = iFirstIndex; iIndex <= iLastIndex ; iIndex++ )
   {
		//  get high byte for 1st character	
	    char ctemp = (char) (dwDiskData [iIndex] / 256);
		char cszmyspace[] = " ";
		if ( !(ctemp == *cszmyspace))
		{
			pcszBuf [iPosition++] = ctemp ;
		}
		 //  get low byte for 2nd character
		char ctemp1 = (char) (dwDiskData [iIndex] % 256);
		if ( !(ctemp1 == *cszmyspace))
		{
			pcszBuf [iPosition++] = ctemp1 ;
		}
   }

      //  end the string 
   pcszBuf[iPosition] = '\0';

      //  cut off the trailing blanks
   for (iIndex = iPosition - 1; iIndex > 0 && isspace(pcszBuf [iIndex]); iIndex--)
      pcszBuf [iIndex] = '\0';

   return pcszBuf;
}

int MasterHardDiskSerial::GetErrorMessage(TCHAR* tszErrorMessage)
{
	if (strlen(m_cszErrorMessage)!=0)
	{
		mbstowcs((wchar_t *)tszErrorMessage,m_cszErrorMessage,sizeof(m_cszErrorMessage));
		return 0;
	}
	else 
		return -1;
}

MasterHardDiskSerial::MasterHardDiskSerial()
{
	SecureZeroMemory(m_cszErrorMessage,sizeof(m_cszErrorMessage));
	SecureZeroMemory(m_cszHardDriveModelNumber,sizeof(m_cszHardDriveModelNumber));
	SecureZeroMemory(m_cszHardDriveSerialNumber,sizeof(m_cszHardDriveSerialNumber));
}

MasterHardDiskSerial::~MasterHardDiskSerial()
{
}
